from application import *
from vec2d import vec2d

SimulationContextId="simulation"
DebugPaneContextId="debugpane"

class AddObjectNotif:
    def __init__(self,object):
        self.object=object
class AddPlayerNotif(AddObjectNotif):    
    pass    
class RemoveObjectNotif:
    def __init__(self,object):
        self.object=object    
 
class ModelPrototypeV(AbstractAnimatedView):
    def __init__(self,model,contextId):
        AbstractAnimatedView.__init__(self, model, contextId)
        try:
            self.pos=self.model.pos        
        except AttributeError:
            self.pos=(0,0)
            
    def Build(self):        
        AbstractAnimatedView.Build(self)
        #remove animation
        self.ClearFrames()
        #create resources 
        surfaces= self.model.prototype.LoadRessources()        
        #animation enabled
        for s in surfaces:            
            bb=s.get_rect()
            pos=(self.pos[0]-bb.width/2, self.pos[1]-bb.height/2)
            self.pick=s.get_rect()
            self.pick.topleft=pos
            self.DrawPrimitive(pygame.Surface.blit, (s, pos))
            #self.DrawPrimitive(pygame.draw.rect, ((255,0,255), self.pick,1))
            self.PushFrame()

class SwitchContextIdNotif(AddObjectNotif):
    def __init__(self,contextId):
        self.contextId=contextId

class GameV(AbstractView):
    def __init__(self,model,contextId):
        AbstractView.__init__(self,model,contextId)
        
    def Build(self):                        
        self.teamchilds=[t.BuildView(DebugPaneContextId) for t in self.model.teams]
        self.otherchilds=[self.model.map.BuildView(self.contextId)]        
        self.otherchilds+=[t.BuildView(self.contextId) for t in self.model.toolpalettes if self.contextId in t.prototype.interfaces]        
        self.childs=self.teamchilds+self.otherchilds
        
    def ProcessModelNotif(self, notif):
        if isinstance(notif,ModelUpdateNotif):
            self.Build()
        elif isinstance(notif,SwitchContextIdNotif):
            self.contextId=notif.contextId
            self.Build()
    def Draw(self,surface):
        AbstractView.Draw(self,surface)
        if self.model.DelayedTasksQueue:                        
            sw,sh=surface.get_size()
            rw=.8
            rh=.1
            #white
            percent=1.-float(len(self.model.DelayedTasksQueue))/self.model.NbDelayedTasks
            r=pygame.Rect(sw*(.5-rw/2.),sh*(.5-rh/2.),sw*rw*percent,sh*rh)
            pygame.draw.rect(surface,(150,150,150),r,0)
            #black
            r=pygame.Rect(sw*(.5-rw/2.)+sw*rw*percent,sh*(.5-rh/2.),sw*rw*(1.-percent),sh*rh)
            pygame.draw.rect(surface,(0,0,0),r,0)
            #border
            r=pygame.Rect(sw*(.5-rw/2.),sh*(.5-rh/2.),sw*rw,sh*rh)
            pygame.draw.rect(surface,(255,255,255),r,3)
            
class PlayerV(AbstractSpriteView):
    def __init__(self,model,contextId):
        AbstractSpriteView.__init__(self,model,contextId)
        self.surface=self.model.prototype.LoadRessources()[0]
    def GetPosition(self):
        return self.model.fcoord*64
    def GetAngle(self):
        return -self.model.angle
    def Draw(self,surface):
        AbstractSpriteView.Draw(self,surface)
        self.model.iaplayer.Draw(surface)
    def GetSurface(self):
        return self.surface
        


class TransientPrototypeSpriteV(AbstractSpriteView):
    def __init__(self, model, contextId):
        AbstractSpriteView.__init__(self, model, contextId)
        self.surface=self.model.prototype.LoadRessources()
    def GetPosition(self):
        return self.model.pos
    def GetAngle(self):
        return self.model.angle
    def GetSurface(self):
        return self.surface[self.GetFrame()]                
    def GetFrame(self):
        if self.model.elapsed>=self.model.total: return len(self.surface)-1
        return int(self.model.elapsed*len(self.surface)/float(self.model.total))

class RemoveAllPlayersNotif:
    pass

class MapV(AbstractCompiledView):
    def Build(self):
        AbstractCompiledView.Build(self)
        self.childs=[c.BuildView(self.contextId)  for r in self.model.map for c in r]
        if self.contextId==DefaultContextId:
            self.childs+=[o.BuildView(self.contextId) for o in self.model.objects]
        self.childs+=[o.BuildView(self.contextId) for o in self.model.transientobjects]            
        self.area=pygame.Rect(10,40,64*self.model.size[0],64*self.model.size[1])        
        self.pick=pygame.Rect(0, 0, self.area.width,self.area.height)
    
        
    def ProcessModelNotif(self, notif):
        if notif.__class__ is ModelUpdateNotif:
            self.Build()
        elif notif.__class__ is AddObjectNotif:
            self.childs.append(notif.object.BuildView(self.contextId))           
        elif notif.__class__ is RemoveObjectNotif:
            self.childs=filter(lambda c:c.model!=notif.object,self.childs)
        
        
class CellSimulationV(ModelPrototypeV):
    def __init__(self, model,contextId):  
        ModelPrototypeV.__init__(self, model,contextId)        
    def Build(self): 
        m=self.model       
        #self.area=pygame.Rect(self.model.pos[0]-32,self.model.pos[1]-32, 64, 64)        
        ModelPrototypeV.Build(self)
        l=[((-1, 0),((255,255,255),(m.pos[0]-32+ 0,m.pos[1]-32+ 0),(m.pos[0]-32+ 0,m.pos[1]-32+64),2)),
           (( 1, 0),((255,255,255),(m.pos[0]-32+62,m.pos[1]-32+ 0),(m.pos[0]-32+62,m.pos[1]-32+64),2)),
           (( 0, 1),((255,255,255),(m.pos[0]-32+ 0,m.pos[1]-32+62),(m.pos[0]-32+64,m.pos[1]-32+62),2)),
           (( 0,-1),((255,255,255),(m.pos[0]-32+ 0,m.pos[1]-32+ 0),(m.pos[0]-32+64,m.pos[1]-32+ 0),2))]
        map=self.model.map
        if not self.model.prototype.walk:
            for d,arg in l:             
                if map.IsWalk(self.model.coord+d):
                    self.DrawPrimitiveOnAllFrames(pygame.draw.line,arg)    

class CellEditionV(ModelPrototypeV):
    def __init__(self, model,contextId):  
        ModelPrototypeV.__init__(self, model,contextId)        
        self.so=GetApplication().game.prototypes['celldebug-so'].LoadRessources()
    def Build(self):
        ModelPrototypeV.Build(self)
        m=self.model        
        if m.prototype.solid==1:            
            self.DrawPrimitiveOnAllFrames(pygame.Surface.blit, (self.so[0], (m.pos[0]-10,m.pos[1])))        
        if m.prototype.transparent==0:            
            self.DrawPrimitiveOnAllFrames(pygame.Surface.blit, (self.so[1], (m.pos[0]+10,m.pos[1])))

class PlayerCornerV(AbstractCompiledView):
    def __init__(self,model,contextId):
        AbstractCompiledView.__init__(self,model,contextId)
        self.pos=0
        self.font=GetApplication().game.prototypes['teamconrner-font'].LoadRessources()[0]

    def Build(self):
        AbstractCompiledView.Build(self)    
        self.ClearPrimitives()        
        if self.pos:                    
            weapon_name=["Pistol","Shotgun","Chaingun","Shrink","Rpg"]
            color=[(120,120,120),(255,255,255)]
            y=self.pos[1]
            y=self.DrawText((self.pos[0],y),"Health:%d%%  Armour:%d%%"%(self.model.hp,self.model.armour),self.font,(255,255,255))
            for i in range(0,len(weapon_name)):
               self.DrawText((self.pos[0],y),"%s:"%(weapon_name[i]),self.font,color[self.model.weapons[i]])
               y=self.DrawText((self.pos[0]+65,y),"%d/%d"%(self.model.ammo[i],self.model.maxammo[i]),self.font,color[self.model.weapons[i]])
            text="Pistol:%d/%d"
            

       
class StatUpdateNotif:      
    pass
                    
class TeamCornerV(AbstractCompiledView):    
    def __init__(self,model,contextId):
        AbstractCompiledView.__init__(self,model,contextId)        
        i = self.model.game.teams.index(self.model)
        n = len(self.model.game.teams)
        pad=5
        xsize=1200
        ysize=900
        ypos=50+64*10
        self.area=pygame.Rect(xsize/n*i+pad,ypos,xsize/n-2*pad,ysize-pad-ypos)
        self.pick=pygame.Rect(self.area)
        self.pick.topleft=(0,0)        
        self.childs_uptodate=False
        self.stat_uptodate=False
        self.font=GetApplication().game.prototypes['teamconrner-font'].LoadRessources()[0]
    def ProcessModelNotif(self, notif):
        if isinstance(notif, ModelUpdateNotif):
            self.childs_uptodate=False
        elif isinstance(notif, StatUpdateNotif):
            self.stat_uptodate=False
                
    def Build(self):
        AbstractCompiledView.Build(self)    
        if self.childs_uptodate==False or self.stat_uptodate==False:
            self.ClearPrimitives()        
            self.DrawPrimitive(pygame.draw.rect, ((255,0,255), self.pick,1))       
        
            text="""Spawn count:%(nbspawn)d\nFrag count:%(nbfrag)d\nShot:%(shot)d\nPrecision: %(precision)2.2d%%"""%self.model.__dict__            
            y = self.DrawText((10,10),text,self.font)
        if self.childs_uptodate==False:
            x=10            
            self.childs=[self.model.face.BuildView(self.contextId)]
            for c in self.model.players:
                v=c.BuildView(self.contextId)
                v.pos=(x,y+10)
                v.Build()
                self.childs.append(v)
                x+=100
        self.childs_uptodate=True
        self.stat_uptodate=True
   
             
        
    def Draw(self,surface):
        if self.childs_uptodate==False or self.stat_uptodate==False: self.Build()
        AbstractCompiledView.Draw(self, surface)
        """if self.area: surface=surface.subsurface(self.area)
        surface.fill((0,0,0))
        for fn, arg in self.primitives:
            fn(surface,*arg)        
        for c in self.childs:
            c.Draw(surface)     """       
    
        
        
        
    

class TransientPrototypeV(AbstractMultiframeView):
    def Build(self):
        AbstractMultiframeView.Build(self)
        #remove animation
        self.ClearFrames()
        #create resources 
        surfaces= self.model.prototype.LoadRessources()
        if(self.model.angle):
            surfaces=[pygame.transform.rotate(c, self.model.angle) for c in surfaces]
        #animation enabled
        for s in surfaces:            
            p0=self.model.pos-vec2d(s.get_rect().size)*.5            
            p0=(int(p0[0]),int(p0[1]))
            self.pick=s.get_rect()
            self.pick.topleft=p0
            self.DrawPrimitive(pygame.Surface.blit,(s,p0))            
            self.PushFrame()        
    def GetFrame(self):
        return int(self.model.elapsed*(len(self.frames)-1)/float(self.model.total))
 
class BulletImpactV(TransientPrototypeV):
    def Build(self):
        TransientPrototypeV.Build(self)   
        self.GotoFrame(0)
        self.DrawPrimitive(pygame.draw.line,((200,200,200),self.model.pos,self.model.p1,2))
    
class GoodV(ModelPrototypeV):    
    def Draw(self,surface):
        if not self.model.remain:
            ModelPrototypeV.Draw(self, surface)
        
        
 
 